<!--
 * hi-region-picker - 省市区选择器
 *
 * @author 济南晨霜信息技术有限公司
 * @mobile 18560000860 / 18754137913
 -->
<template>
    <view class="hi-region-picker" :class="_classes" :style="_styles" v-if="show">
        <!-- 遮罩 -->
        <hi-overlay class="hi-region-picker__overlay" :show="show" align="center-bottom" @close="handleMaskClick" v-if="mask" v-bind="maskOpts"></hi-overlay>

        <!-- 内容 -->
        <view class="hi-region-picker__content">
            <!-- Header -->
            <view class="hi-region-picker__header">
                <view class="hi-region-picker__header__button hi-region-picker__header__button--cancel" @tap="handleCancel" hover-class="hi-hover">
                    {{ cancelText }}
                </view>
                <view class="hi-region-picker__header__title hi-line-1">{{ title }}</view>
                <view class="hi-region-picker__header__button hi-region-picker__header__button--confirm" @tap="handleConfirm" hover-class="hi-hover">
                    {{ confirmText }}
                </view>
            </view>

            <!-- picker-view -->
            <picker-view class="hi-region-picker__picker-view" :value="values" :indicator-style="_indicatorStyle" @change="onChange">
                <!-- 省 -->
                <picker-view-column class="hi-region-picker__column hi-region-picker__column--province">
                    <view class="hi-region-picker__column__item hi-region-picker__column__item--province" v-for="(item, index) in provinceList" :key="index">
                        {{ item[keyName] }}
                    </view>
                    <!-- 至少保留一个，否则会默认滚动到下标为1的选项 -->
                    <view class="hi-region-picker__column__item hi-region-picker__column__item--province" v-if="!provinceList.length"></view>
                </picker-view-column>

                <!-- 市 -->
                <picker-view-column class="hi-region-picker__column hi-region-picker__column--city">
                    <view class="hi-region-picker__column__item hi-region-picker__column__item--city" v-for="(item, index) in cityList" :key="index">
                        {{ item[keyName] }}
                    </view>
                    <!-- 至少保留一个，否则会默认滚动到下标为1的选项 -->
                    <view class="hi-region-picker__column__item hi-region-picker__column__item--city" v-if="!cityList.length"></view>
                </picker-view-column>

                <!-- 区 -->
                <picker-view-column class="hi-region-picker__column hi-region-picker__column--area">
                    <view class="hi-region-picker__column__item hi-region-picker__column__item--area" v-for="(item, index) in areaList" :key="index">
                        {{ item[keyName] }}
                    </view>
                    <!-- 至少保留一个，否则会默认滚动到下标为1的选项 -->
                    <view class="hi-region-picker__column__item hi-region-picker__column__item--area" v-if="!areaList.length"></view>
                </picker-view-column>
            </picker-view>

            <!-- loading -->
            <view class="hi-region-picker__loading" v-if="loading">
                <hi-loading v-bind="loadingOpts"></hi-loading>
            </view>
        </view>
    </view>
</template>

<!-- 由于 HbuilderX 不支持 defineOptions() 写法，故只能在此处进行配置 -->
<script>
    export default { options: uni?.$hi?.config?.componentsOptions || {} };
</script>

<script setup>
    import { ref, computed, onMounted } from "vue";
    import props from "./props.js";

    // 组件属性
    const _props = defineProps(props);

    // emits
    const _emits = defineEmits(["change", "close", "confirm", "cancel", "changeProvince", "changeCity", "changeArea", "maskClick"]);

    // 组件类名
    const _classes = computed(() => {
        const classes = [];

        // 是否显示
        if (_props.show) classes.push("hi-region-picker--show");

        return classes;
    });

    // 组件样式
    const _styles = computed(() => {
        const styles = [];

        // 遮罩背景
        if (_props.maskBg) styles.push(`--hi-overlay-background: ${_props.maskBg};`);

        // 背景
        if (_props.bg) styles.push(`--hi-region-picker-background: ${_props.bg};`);

        // 圆角
        if (_props.radius) styles.push(`--hi-region-picker-border-radius: ${_props.radius};`);

        // 高度
        if (_props.height) styles.push(`--hi-region-picker-height: ${_props.height};`);

        // 最大高度
        if (_props.maxHeight) styles.push(`--hi-region-picker-max-height: ${_props.maxHeight};`);

        // item 高度
        if (_props.itemHeight) styles.push(`--hi-region-picker-item-height: ${_props.itemHeight};`);

        // item 文字大小
        if (_props.itemFontSize) styles.push(`--hi-region-picker-item-font-size: ${_props.itemFontSize};`);

        // item 文字颜色
        if (_props.itemColor) styles.push(`--hi-region-picker-item-color: ${_props.itemColor};`);

        // 标题颜色
        if (_props.titleColor) styles.push(`--hi-region-picker-title-color: ${_props.titleColor};`);

        // 标题大小
        if (_props.titleFontSize) styles.push(`--hi-region-picker-title-font-size: ${_props.titleFontSize};`);

        // 标题粗细
        if (_props.titleFontWeight) styles.push(`--hi-region-picker-title-font-weight: ${_props.titleFontWeight};`);

        // 取消按钮文字颜色
        if (_props.cancelColor) styles.push(`--hi-region-picker-cancel-color: ${_props.cancelColor};`);

        // 取消按钮文字大小
        if (_props.cancelFontSize) styles.push(`--hi-region-picker-cancel-font-size: ${_props.cancelFontSize};`);

        // 确认按钮文字颜色
        if (_props.confirmColor) styles.push(`--hi-region-picker-confirm-color: ${_props.confirmColor};`);

        // 确认按钮文字大小
        if (_props.confirmFontSize) styles.push(`--hi-region-picker-confirm-font-size: ${_props.confirmFontSize};`);

        return styles;
    });

    // 选择器中间选中框的样式
    const _indicatorStyle = computed(() => {
        return `height: var(--hi-region-picker-item-height);`;
    });

    // 选中项下标
    const _values = ref([]);

    // 省数据
    const provinceList = computed(() => {
        if (_props?.region) return _props.region;
        return _props.provinces;
    });

    // 市数据
    const cityList = computed(() => {
        const provinceIndex = _values.value[0];
        if (_props?.region) return _props.region?.[provinceIndex]?.children || [];
        return _props.cities;
    });

    // 区数据
    const areaList = computed(() => {
        const provinceIndex = _values.value[0];
        const cityIndex = _values.value[1];
        if (_props?.region) return _props.region?.[provinceIndex]?.children?.[cityIndex]?.children || [];
        return _props.areas;
    });

    // 初始化时设置默认选中项下标
    onMounted(() => {
        _values.value = _props.values;
    });

    /**
     * 当滚动选择，value 改变时触发 change 事件
     * @param {Object} event event.detail = {value: value}；value为数组，表示 picker-view 内的 picker-view-column 当前选择的是第几项（下标从 0 开始）
     */
    function onChange(event) {
        const value = event.detail.value.slice(0, 3);

        // 判断滚动的是哪一列
        if (value[0] !== _values.value[0]) {
            // 如果切换后需要将市和区重置为0，则需要将value[1]和value[2]重置为0
            if (_props.returnZero) {
                value[1] = 0;
                value[2] = 0;
            }

            _emits("change", value, getSelectedDatas(value));
            _emits("changeProvince", value[0], getSelectedProvinceData(value));
        } else if (value[1] !== _values.value[1]) {
            // 如果切换后需要将区重置为0，value[2]重置为0
            if (_props.returnZero) {
                value[2] = 0;
            }
            _emits("change", value, getSelectedDatas(value));
            _emits("changeCity", value[1], getSelectedCityData(value));
        } else {
            _emits("change", value, getSelectedDatas(value));
            _emits("changeArea", value[2], getSelectedAreaData(value));
        }

        // 更新内部选中项下标
        _values.value = value;
    }

    /**
     * 获取选中的数据
     * @param {Array} values 当前选中项的下标
     */
    function getSelectedDatas(values) {
        return {
            province: getSelectedProvinceData(values),
            city: getSelectedCityData(values),
            area: getSelectedAreaData(values)
        };
    }

    /**
     * 获取选中的省份数据
     * @param {Array} values 选中的省市区数据下标
     */
    function getSelectedProvinceData(values) {
        const provinceIndex = values[0];
        if (_props.region) return _props.region[provinceIndex];
        return _props.provinces[provinceIndex];
    }

    /**
     * 获取选中的城市数据
     * @param {Array} values 选中的省市区数据下标
     */
    function getSelectedCityData(values) {
        const provinceIndex = values[0];
        const cityIndex = values[1];
        if (_props.region) return _props.region[provinceIndex].children[cityIndex];
        return _props.cities[cityIndex];
    }

    /**
     * 获取选中的地区数据
     * @param {Array} values 选中的省市区数据下标
     */
    function getSelectedAreaData(values) {
        const provinceIndex = values[0];
        const cityIndex = values[1];
        const areaIndex = values[2];
        if (_props.region) return _props.region[provinceIndex].children[cityIndex].children[areaIndex];
        return _props.areas[areaIndex];
    }

    /**
     * 遮罩点击事件
     */
    function handleMaskClick() {
        _emits("maskClick");
        if (_props.closeOnClickOverlay) {
            _emits("close");
        }
    }

    /**
     * 取消事件
     */
    function handleCancel() {
        _emits("cancel");
    }

    /**
     * 确认事件
     */
    function handleConfirm() {
        _emits("confirm", _values.value, getSelectedDatas(_values.value));
    }
</script>

<style lang="scss" scoped>
    .hi-region-picker {
        &__content {
            background: var(--hi-region-picker-background, var(--hi-background-element));
            border-radius: var(--hi-region-picker-border-radius, 8px) var(--hi-region-picker-border-radius, 8px) 0 0;
            max-height: var(--hi-region-picker-max-height, 80%);
            height: var(--hi-region-picker-height, 50%);
            width: var(--hi-region-picker-width, 100%);
            display: var(--hi-region-picker-display, flex);
            flex-direction: var(--hi-region-picker-flex-direction, column);
            padding: var(--hi-region-picker-padding, 0 20px);
            position: var(--hi-region-picker-position, fixed);
            left: var(--hi-region-picker-left, 0);
            bottom: var(--hi-region-picker-bottom, 0);
            z-index: var(--hi-region-picker-z-index, var(--hi-index-upper));
            animation-duration: var(--hi-region-picker-animation-duration, 300ms);
            animation-fill-mode: var(--hi-region-picker-animation-fill-mode, forwards);
            animation-timing-function: var(--hi-region-picker-animation-timing-function, linear);
        }

        &__header {
            display: var(--hi-region-picker-header-display, flex);
            align-items: var(--hi-region-picker-header-align-items, center);
            flex-shrink: var(--hi-region-picker-header-flex-shrink, 0);
            margin: var(--hi-region-picker-header-margin, 0 0 30px 0);
            padding: var(--hi-region-picker-header-padding, 30rpx 0);

            &__button {
                flex-shrink: var(--hi-region-picker-button-flex-shrink, 0);
                font-weight: var(--hi-region-picker-button-font-weight, 500);
                flex: var(--hi-region-picker-button-flex, 1);
                display: var(--hi-region-picker-button-display, flex);
                flex-direction: var(--hi-region-picker-button-flex-direction, row);

                &--cancel {
                    font-size: var(--hi-region-picker-cancel-font-size, inherit);
                    color: var(--hi-region-picker-cancel-color, var(--hi-color-middle));
                    font-weight: var(--hi-region-picker-cancel-font-weight, var(--hi-region-picker-button-font-weight, 500));
                    justify-content: var(--hi-region-picker-cancel-justify-content, flex-start);
                }

                &--confirm {
                    font-size: var(--hi-region-picker-confirm-font-size, inherit);
                    color: var(--hi-region-picker-confirm-color, var(--hi-theme-primary));
                    font-weight: var(--hi-region-picker-confirm-font-weight, var(--hi-region-picker-button-font-weight, 500));
                    justify-content: var(--hi-region-picker-confirm-justify-content, flex-end);
                }
            }

            &__title {
                flex: var(--hi-region-picker-title-flex, 2);
                font-weight: var(--hi-region-picker-title-font-weight, 700);
                color: var(--hi-region-picker-title-color, inherit);
                font-size: var(--hi-region-picker-title-font-size, 1.25em);
                text-align: var(--hi-region-picker-title-text-align, center);
                flex-shrink: var(--hi-region-picker-title-flex-shrink, 0);
            }
        }

        &__picker-view {
            width: var(--hi-region-picker-picker-view-width, 100%);
            flex: var(--hi-region-picker-picker-view-flex, 1);
        }

        &__column {
            &__item {
                height: var(--hi-region-picker-item-height, 3.5em);
                display: var(--hi-region-picker-item-display, flex);
                align-items: var(--hi-region-picker-item-align-items, center);
                justify-content: var(--hi-region-picker-item-justify-content, center);
                color: var(--hi-region-picker-item-color, inherit);
                font-size: var(--hi-region-picker-item-font-size, inherit);
                font-weight: var(--hi-region-picker-item-font-weight, 500);
            }
        }

        .uni-picker-view-indicator {
            height: var(--hi-region-picker-item-height, 3.5em) !important;
        }

        &__loading {
            position: var(--hi-region-picker-loading-position, absolute);
            width: var(--hi-region-picker-loading-width, 100%);
            height: var(--hi-region-picker-loading-height, 100%);
            left: var(--hi-region-picker-loading-left, 0);
            top: var(--hi-region-picker-loading-top, 0);
            bottom: var(--hi-region-picker-loading-bottom, 0);
            right: var(--hi-region-picker-loading-right, 0);
            display: var(--hi-region-picker-loading-display, flex);
            flex-direction: var(--hi-region-picker-loading-flex-direction, column);
            align-items: var(--hi-region-picker-loading-align-items, center);
            justify-content: var(--hi-region-picker-loading-justify-content, center);
            background: var(--hi-region-picker-loading-background, var(--hi-background-element));
            z-index: var(--hi-region-picker-loading-z-index, 6);
            font-size: var(--hi-region-picker-loading-font-size, 1.5em);
            opacity: var(--hi-region-picker-loading-opacity, 0.8);
            pointer-events: none;
        }

        &--show {
            .hi-region-picker__content {
                animation-name: hi-region-picker-content-animate;
            }
        }

        @keyframes hi-region-picker-content-animate {
            0% {
                transform: translateY(100%);
                opacity: 0;
            }
            100% {
                transform: translateY(0);
                opacity: 1;
            }
        }
    }
</style>
